package com.foo.designpattern.strategy;

import junit.framework.TestCase;

/**
 * com.foo.designpattern.strategy
 * Created with IntelliJ IDEA.
 * Created by jiang on 2016-05-17 14:36.
 *
 * @Description 测试类：策略模式(Strategy)
 * 策略模式属于对象的行为模式。其用意是针对一组算法，将每一个算法封装到具有共同接口的独立类中，从而使得它们可以相互替换。
 * 策略模式使得算法可以在不影响到客户端的情况下发生变化。
 * <p/>
 * 策略模式涉及到三个角色：
 * 1、环境(Context)角色：持有一个Strategy的引用。
 * 2、抽象策略(Strategy)角色：此角色给出所有的具体策略类所需的接口，通常由一个接口或抽象类实现。
 * 3、具体策略(Concrete Strategy)角色：包装了相关的算法或行为。
 * <p/>
 * 本例场景：某图书售卖网站中，针对不同等级的会员享受不同的折扣。
 * 比如网站对初级会员享受10%的折扣，对中级会员享受30%的折扣，对高级会员享受50%的折扣。
 * <p/>
 * 认识策略模式：
 * 1、策略模式的重心：
 * 策略模式的中心并不是如何实现算法，而是如何组织、调用这些算法，从而让程序结构更灵活，具有更好的维护性和扩展性。
 * 2、算法的平等性：
 * 策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法，大家的地位是完全一样的，正因为这个平等性，才能实现算法之间的相互替换。
 * 所有的策略算法在实现上也是相互独立的，相互之间是没有依赖的。策略算法是相同行为的不同实现。
 * 3、运行时策略的唯一性：
 * 运行期间，策略模式在每一个时刻只能使用一个具体的策略实现对象，虽然可以动态地在不同的策略实现中切换，但是同时只能使用一个。
 * 策略模式的决定权在用户，系统本身提供不同算法的实现，新增或者删除算法，对各种算法做封装。
 * 因此，策略模式多用在算法角色系统中，外部用户只需要决定使用那个算法即可。
 * 4、公有的行为：
 * 经常见到的是，所有的具体策略类都有一些公有的行为。这时候，就应当把这些公有的行为放到抽象的策略角色类(Strategy)里面。
 * 当然这时候抽象策略角色必须要用抽象类实现，而不能使用接口。这其实也是典型的将代码向继承等级结构的上方集中的标准做法。
 * <p/>
 * 策略模式的优点：
 * 1、策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面，从而避免代码重复。
 * 2、使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护，它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起，
 * 统统列在一个多重条件语句里面，比使用继承的办法还要原始和落后。
 * <p/>
 * 策略模式的缺点：
 * 1、客户端必须知道所有的策略类，并自行决定使用哪一种策略类。这就意味着客户端必须理解这些算法的区别，
 * 以便恰当地选择算法类。换言之，策略模式只适用于客户端知道算法或行为的情况。
 * 2、由于策略模式把每个具体的策略实现都单独封装成类，如果备选的策略很多的话，那么对象的数据就会很可观。
 */

public class StrategyTestCase extends TestCase {
    public void testStrategy() {
        System.out.println("= = = = ↓↓↓策略模式，测试开始↓↓↓ = = = =");

        // 选择并创建需要使用的策略对象：初级会员
        MemberStrategy member1 = new PrimaryMemberStrategy();
        // 创建环境
        Price price1 = new Price(member1);
        // 计算价格
        double quote1 = price1.quote(300);
        System.out.println("初级会员的图书的最终价格为：" + quote1);

        // 选择并创建需要使用的策略对象：中级会员
        MemberStrategy member2 = new IntermediateMemberStrategy();
        // 创建环境
        Price price2 = new Price(member2);
        // 计算价格
        double quote2 = price2.quote(300);
        System.out.println("中级会员的图书的最终价格为：" + quote2);

        // 选择并创建需要使用的策略对象：高级会员
        MemberStrategy member3 = new AdvancedMemberStrategy();
        // 创建环境
        Price price3 = new Price(member3);
        // 计算价格
        double quote3 = price3.quote(300);
        System.out.println("高级会员的图书的最终价格为：" + quote3);

        System.out.println("= = = = ↑↑↑策略模式，测试结束↑↑↑ = = = =");
    }
}
